/**全局加载状态类 */
import svgDoms from "./svgDoms";
export class WLoading {
  constructor({
    domSelector,
    zIndex = 100,
    backgroundColor = "rgba(0,0,0,0.4)",
    svgTyp = "line5",
    svgSize = "auto",
    svgColor = "#FF6700",
    imgSrc = '',
    imgClass = '',
    imgStyle = '',
  }) {
    if (typeof document == 'undefined') throw "非浏览器环境";
    this.domSelector = domSelector;

    this.key = parseInt(Math.random() * 1000); //唯一标识
    this.lCount = 0; //当前加载量
    this.zIndex = zIndex; //默认层级
    this.backgroundColor = backgroundColor; //默认颜色

    this.svgTyp = svgTyp;
    this.svgSize = svgSize;
    this.svgColor = svgColor;

    this.imgSrc = imgSrc;
    this.imgClass = imgClass;
    this.imgStyle = imgStyle;
  }
  //获取目标dom
  getLDom() {
    if (!this.domSelector) return;
    return document.querySelector(this.domSelector);
  }
  //获取加载状态dom
  getLDiaDom() {
    if (!this.diaDomSelector) return;
    return document.querySelector(this.diaDomSelector);
  }
  //设置目标dom
  setLoadingDom(domSelector) {
    if (domSelector) {
      this.domSelector = domSelector;
      this.setDomWatcher(this.getLDom());//重置监听
      this.setLoadingDiaDomStyle();//重置加载元素样式
    }
  }
  //设置dom监听
  setDomWatcher(dom) {
    if (!dom) return;
    if (!this.mutationObserver)
      this.mutationObserver = new MutationObserver(
        debounced((mutationsList) => {
          for (let mutation of mutationsList) {
            if (
              mutation.type === "childList" ||
              mutation.type === "attributes"
            ) {
              this.setLoadingDiaDomStyle();
            }
          }
        })
      );

    if (!this.resizeObserver)
      this.resizeObserver = new ResizeObserver(
        debounced((entries) => {
          for (const entry of entries) {
            this.setLoadingDiaDomStyle();
          }
        })
      );

    this.closeDomWatcher(); //关闭监听
    this.mutationObserver.observe(dom, {
      attributes: true,
      childList: true,
      subtree: true,
    });
    this.resizeObserver.observe(dom);
    this.scrollEvt = () => {
      this.setLoadingDiaDomStyle();
    }
    this.resizeEvt = () => {
      this.setLoadingDiaDomStyle();
    }
    window.addEventListener("scroll", this.scrollEvt);
    window.addEventListener("resize", this.resizeEvt);
    this.hasWatcher = true;
  }
  //关闭监听
  closeDomWatcher() {
    if (this.mutationObserver) this.mutationObserver.disconnect(); //关闭监听
    if (this.resizeObserver) this.resizeObserver.disconnect(); //关闭监听
    window.removeEventListener("scroll", this.scrollEvt);
    window.removeEventListener("resize", this.resizeEvt);
    this.hasWatcher = false;
  }
  //创建加载元素
  createLoadingDiaDom() {
    let lDom = this.getLDom();
    let lDiaDom = this.getLDiaDom();
    if (!lDom || lDiaDom) return;
    lDiaDom = document.createElement("div");
    lDiaDom.setAttribute("class", `dia_loading_${this.key}`);
    document.body.appendChild(lDiaDom);
    this.diaDomSelector = `.dia_loading_${this.key}`;
    this.setLoadingDiaDomStyle(true);
  }
  // 设置加载元素样式
  setLoadingDiaDomStyle(first) {
    let lDom = this.getLDom();
    let lDiaDom = this.getLDiaDom();
    if (!lDiaDom) return;
    if (!lDom) return this.destroy();
    let rectObj = lDom.getBoundingClientRect();
    lDiaDom.setAttribute(
      "style",
      `width:${rectObj.width}px;
        height:${rectObj.height}px;
        position:fixed;
        top:${rectObj.top}px;
        left:${rectObj.left}px;
        z-index:${this.zIndex};
        background-color:${this.backgroundColor};
        display:flex;justify-content: center;align-items: center;`
    );
    if (this.imgSrc) {
      if (first) lDiaDom.innerHTML = `<img class="${this.imgClass}" style="${this.imgStyle}" src="${this.imgSrc}" alt="error" />`;
    } else {
      let size = 1;
      if (this.svgSize == "auto") size = rectObj.width > 1200 ? 3 : 2;
      else size = this.svgSize;
      lDiaDom.innerHTML = svgDoms[this.svgTyp](size, this.svgColor);
    }
  }
  //是否是dom对象
  isDOMElement(object) {
    return (
      typeof object === "object" &&
      object !== null &&
      object.nodeType === 1 &&
      "ownerDocument" in object &&
      "attributes" in object
    );
  }

  //显示加载
  show() {
    let lDom = this.getLDom();
    if (!lDom) throw `目标元素不存在`;
    let lDiaDom = this.getLDiaDom();
    if (!lDiaDom) this.createLoadingDiaDom();
    if(!this.hasWatcher) this.setDomWatcher(lDom);
    this.lCount += 1;
  }
  //隐藏加载
  hide() {
    this.lCount -= 1;
    if (this.lCount < 0) this.lCount = 0;
    if(this.lCount==0) this.destroy();
  }
  //销毁
  destroy() {
    this.lCount = 0;
    let lDiaDom = this.getLDiaDom();
    if (lDiaDom) lDiaDom.remove();
    this.closeDomWatcher(); //关闭监听
  }
}

/**
 * @des 防抖 ，多次只执行最后一次
 * @param func 需要包装的函数
 * @param delay 延迟时间，单位ms
 * @param immediate 是否默认执行一次(第一次不延迟)
 */
function debounced(func, delay = 200, immediate = false) {
  let timer;
  return function (...args) {
    if (immediate) {
      func(...args);
      immediate = false;
      return;
    }
    clearTimeout(timer);
    timer = setTimeout(() => {
      func(...args);
    }, delay);
  };
}

/**自定义加载类 */
export class WCustomLoading extends WLoading {
  constructor(options) {
    super(options);
    this.diaDomSelector = options.diaDomSelector; //自定义加载组件
  }

  //创建加载元素
  createLoadingDiaDom() { }
  // 设置加载元素样式
  setLoadingDiaDomStyle() {
    let lDom = this.getLDom();
    let lDiaDom = this.getLDiaDom();
    if (!lDiaDom) return;
    if (!lDom) return this.destroy();
    let rectObj = lDom.getBoundingClientRect();
    lDiaDom.setAttribute(
      "style",
      `width:${rectObj.width}px;
        height:${rectObj.height}px;
        position:fixed;
        top:${rectObj.top}px;
        left:${rectObj.left}px;
        z-index:${this.zIndex};
        display:block;
        box-sizing: border-box;`
    );
  }

  //销毁
  destroy() {
    this.lCount = 0;
    let lDiaDom = this.getLDiaDom();
    if (lDiaDom) lDiaDom.setAttribute( "style", `display:none;` );
    this.closeDomWatcher(); //关闭监听
  }
}